package net.gdface.worker;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

import net.gdface.utils.Assert;

/**
 * 工作数据容器<br>
 * 用{@link ConcurrentHashMap}管理在线程间传递的工作对象的数据（局部变量），<br>
 * 这些对象数据以{@link String}为key检索读写,伴随一项任务在各个线程间传递。<br>
 *  该类实现了{@link Delayed}接口，支持延时队列{@link java.util.concurrent.DelayQueue}
 * @author guyadong
 *
 */
public class WorkData implements Delayed {
	private final ConcurrentMap<String,Object> variables = new ConcurrentHashMap<String,Object>();
	public static final WorkDataManager WOKING_DATA=new WorkDataManager();
    /** Base of nanosecond timings, to avoid wrapping */
    private static final long NANO_ORIGIN = System.nanoTime();
	/** 以 {@link #NANO_ORIGIN}为基准的时间 */
	private long time;

	public WorkData() {
		this(0L);
	}

	public WorkData(long dueTime,TimeUnit unit) {
		setDelay(dueTime,unit);
	}
	
	public WorkData(long dueTimeMills) {
		this(dueTimeMills,TimeUnit.MILLISECONDS);
	}
	
	/**
	 * 根据指定的{@code interval}间隔，生成到期时间
	 * @param interval 从当前时间算起,指定多长时间后到期
	 * @param unit 时间单位对象
	 * @return 到期时间
	 * @see #now()
	 */
	private final long newDueTime(long interval,TimeUnit unit) {
		return now()+unit.convert(interval, TimeUnit.NANOSECONDS);
	}
    /**
     * @return nanosecond time offset by origin
     */
    private final long now() {
        return System.nanoTime() - NANO_ORIGIN;
    }
	/**
	 * @param delayMills 从当前算起的延时时间(毫秒)
	 * @return 当前对象
	 * @see #setDelay(long, TimeUnit)
	 */
	public WorkData setDelay(long delayMills) {
		return setDelay(delayMills,TimeUnit.MILLISECONDS);
	}

	/**
	 * @param delay  从当前算起的延时时间
	 * @param unit 
	 * @return 当前对象
	 * @see #newDueTime(long, TimeUnit)
	 */
	public WorkData setDelay(long delay,TimeUnit unit) {
		this.time = newDueTime(delay,unit);
		return this;
	}
	

	/**
	 * 局部变量定义赋值<br>
	 * {@code value}为null时，清除{@code name}对应的值
	 * @param name 变量名
	 * @param value 变量值
	 * @return the previous value associated with key, or null if there was no mapping for key.
	 * @see java.util.concurrent.ConcurrentHashMap#put(java.lang.Object, java.lang.Object)
	 */
	@SuppressWarnings("unchecked")
	public <T> T setVariables(String name, T value) {
		Assert.notEmpty(name, "name");
		return  (T) ((null == value) ? variables.remove(name) :variables.put(name, value));
	}

	/**
	 * 获取局部变量<br>
	 * @param name 变量名
	 * @return  变量值 指定的变量未定义时返回null
	 * @see java.util.concurrent.ConcurrentHashMap#get(java.lang.Object)
	 */
	@SuppressWarnings("unchecked")
	public <T> T getVariables(String name) {
		return  (T) variables.get(name);
	}

	/**
	 * 将所有局部变量初化为空
	 * @see java.util.concurrent.ConcurrentHashMap#clear()
	 */
	public void initAllVariables() {
		variables.clear();
	}

	@Override
	public int compareTo(Delayed o) {
		if (o == null || !(o instanceof WorkData))
			return 1;
		else if (this.time == ((WorkData) o).time)
			return 0;
		else 
			return this.time > ((WorkData) o).time ? 1 : -1;
	}

	@Override
	public long getDelay(TimeUnit unit) {
		 return unit.convert(time - now(), TimeUnit.NANOSECONDS);
	}

}